package cn.smp.protocol;

import cn.smp.message.Message;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageCodec;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.List;

@Slf4j
//@ChannelHandler.Sharable Be aware that sub-classes of ByteToMessageCodec MUST NOT annotated with @Sharable.
public class MessageCodec extends ByteToMessageCodec<Message> {

    @Override
    protected void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out) throws Exception {
        //1.4字节魔数
        out.writeBytes(new byte[]{1,2,3,4});
        //2.1字节版本
        out.writeByte(1);
        //3.1字节的序列号方式 jdk 0,json 1
        out.writeByte(0);
        //4.1字节的指令类型
        out.writeByte(msg.getMessageType());
        //5.4个字节的请求序号
        out.writeInt(msg.getSequenceId());
        //无意义，对齐填充
        out.writeByte(0xff);

        //6.内容的字节数组
        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
        final ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(msg);
        final byte[] bytes = bos.toByteArray();
        //7.长度
        out.writeInt(bytes.length);
        //8.写入内容
        out.writeBytes(bytes);
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        final int magicNum = in.readInt();
        final byte version = in.readByte();
        final int serializerType = in.readByte();
        final byte messageType = in.readByte();
        final int sequenceId = in.readInt();
        in.readByte();
        final int length = in.readInt();
        final byte[] bytes = new byte[length];
        in.readBytes(bytes,0,length);
        final ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
        final Message msg = (Message) ois.readObject();

        log.debug("{},{},{},{},{},{}",magicNum,version,serializerType,messageType,sequenceId,length);
        log.debug("{}",msg);

        out.add(msg);
    }
}

